package midend.IR_Instruction;

import midend.IR_Type.IR_Int32;
import midend.IR_Type.IR_Pointer;
import midend.IR_Type.IR_Type;
import midend.IR_Value.IR_BaseBlock;
import midend.IR_Value.IR_FuncBlock;
import midend.IR_Value.IR_Local_Value;
import midend.IR_Value.IR_Value;

import java.util.ArrayList;
import java.util.List;

public class Pointer_Instruction extends Instruction{
    private IR_Value base;
    private List<IR_Value> mylist;

    public Pointer_Instruction(List<IR_Value> op, IR_BaseBlock bb) {
        super(op, bb);
        this.base = op.get(1);
        addValue(base);
        this.mylist = new ArrayList<>();
        for(int i = 2;i < op.size();i++){
            mylist.add(op.get(i));
            addValue(op.get(i));
        }
    }

    public void updateop(int index, IR_Value newValue) {
        set_Op(index + 1, newValue);
        if(index == 0){
            set_Base(newValue);
        }
        else{
            mylist.set(index - 1, newValue);
        }
    }
    public IR_Value get_base() {
        return base;
    }

    public void set_Base(IR_Value base) {
        this.base = base;
        set_Op(1, base);
    }

    public List<IR_Value> get_list() {
        return mylist;
    }

    public void set_List(List<IR_Value> mylist) {
        this.mylist = mylist;
    }

    public void set_List(int i, IR_Value new_Value) {
        this.mylist.set(i, new_Value);
        set_Op(i + 2, new_Value);
    }


    @Override
    public String toString() {
        StringBuilder s = new StringBuilder();
        IR_Value res = get_op().get(0);
        IR_Type baseType = ((IR_Pointer)base.get_Type()).get_Base_Type();
        for(IR_Value l : mylist){
            s.append(", ").append(IR_Int32.IR_Int32().get_TypeName()).append(" ").append(l.get_ValueName());
        }
        return res.get_ValueName() + " = getelementptr " + baseType.get_TypeName() + ", " +
                base.get_Type().get_TypeName() + " " + base.get_ValueName() + s.toString();
    }


    @Override
    public Pointer_Instruction clone(IR_BaseBlock block) {
        String copy_name = ((IR_Local_Value) get_op().get(0)).get_Local_Identity();
        IR_Type copy_type = get_op().get(0).get_Type();
        IR_Value res = new IR_Local_Value(copy_name, copy_type);
        ArrayList<IR_Value> copy_ops = new ArrayList<>();
        copy_ops.add(res);
        for (int i = 1 ; i< get_op().size() ; i++) {
            IR_Value copy_op  = get_op().get(i);
            if(IR_FuncBlock.cloneMap_Value.containsKey(copy_op)) {
                copy_op = IR_FuncBlock.cloneMap_Value.get(copy_op);
            }
            copy_ops.add(copy_op);
        }
        Pointer_Instruction copy_ins = new Pointer_Instruction(copy_ops, block);
        return copy_ins;
    }
}
